package protomysql

import (
	"gitee.com/crack007/goose/gslog"
	"gitee.com/crack007/proxy/src/constant"
	"gitee.com/crack007/proxy/src/proxy/protocol/protomysql/mysqlfield"
)

const (
	RESP_ERR = 0xFF
)

// 处理来自 server 的消息。
type MysqlServer struct {
	handshakeV10 *mysqlfield.HandshakeV10
	PrepareState int
}

func NewMysqlServer() *MysqlServer {
	return &MysqlServer{}
}
func (s *MysqlServer) Process(data []byte, mysql *Mysql) {
	mysqlPackage := NewMysqlPackage(data)
	if s.handshakeV10 == nil {
		mysqlPackage.Init()
		s.handshakeV10 = loadHandshake(mysqlPackage.PayloadStream)
		return
	}

	mysqlPackage.InitServer()
	if mysqlPackage.ResponseCode == RESP_ERR {
		errorCode := mysqlPackage.PayloadStream.ReadFixedLengthInteger(2)
		sqlState := ""
		msg := ""
		if s.handshakeV10.ServerCapabilities&constant.ClientProtocol41 == constant.ClientProtocol41 {
			mysqlPackage.PayloadStream.Skip(1)
			sqlState = mysqlPackage.PayloadStream.ReadFixedLengthString(5)
			msg = mysqlPackage.PayloadStream.ReadRestOfPacketString()
		}

		gslog.Warn("err:%s \r\ncode:%d sql_state:%s msg:%s", mysql.MysqlClient.GetSql(), errorCode, sqlState, msg)
		return
	}

	if s.PrepareState == constant.STMT_STATE_PREPARE {
		// client 已发送 prepare 查询，获得的是 PREPARE_OK 响应包
		loadMysqlSTMTPrepareOk(mysql.MysqlClient.Stmt.StmtPrepareOk, mysqlPackage.PayloadStream)
		s.ChangePrepareState(constant.STMT_STATE_PREPARE_OK)
		return
	}

	if s.PrepareState == constant.COM_STMT_EXECUTE {
		// 已进入 execute 阶段，获取的是 COM_STMT_EXECUTE Response 包
		mysql.MysqlClient.profileEnd()
		// 打印 sql。
		mysql.DumpSql(mysql.MysqlClient.Stmt.PrepareSql, mysql.MysqlClient.IsSlowQuery())
		return
	}

	if mysql.MysqlClient.ComQuery != "" {
		mysql.MysqlClient.profileEnd()
		mysql.DumpSql(mysql.MysqlClient.ComQuery, mysql.MysqlClient.IsSlowQuery())
		mysql.Reset()
	}

}
func (s *MysqlServer) ChangePrepareState(state int) {
	s.PrepareState = state
}

func (s *MysqlServer) Reset() {
	s.PrepareState = 0
}
